using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Threading.Tasks;
using ThridGroup.ERP.Application.Contracts.DTO.Common;
using ThridGroup.ERP.Application.Contracts.DTO.WarehouseManagement;
using ThridGroup.ERP.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories;

namespace ThridGroup.ERP.WarehouseManagement
{
    /// <summary>
    /// 库位设置服务实现
    /// </summary>
    public class WarehouseLocationSettingService : ERPAppService, IWarehouseLocationSettingService
    {
        private readonly IRepository<WarehouseLocationSettingModel, int> _warehouseLocationSettingRepository;
        private readonly IRepository<WarehouseAreaSettingModel, int> _warehouseAreaSettingRepository;
        private readonly IRepository<WarehouseSettingModel, int> _warehouseSettingRepository;
        private readonly ERPDbContext _dbContext;

        public WarehouseLocationSettingService(
            IRepository<WarehouseLocationSettingModel, int> warehouseLocationSettingRepository,
            IRepository<WarehouseAreaSettingModel, int> warehouseAreaSettingRepository,
            IRepository<WarehouseSettingModel, int> warehouseSettingRepository,
            ERPDbContext dbContext)
        {
            _warehouseLocationSettingRepository = warehouseLocationSettingRepository;
            _warehouseAreaSettingRepository = warehouseAreaSettingRepository;
            _warehouseSettingRepository = warehouseSettingRepository;
            _dbContext = dbContext;
        }

        /// <summary>
        /// 获取库位设置列表
        /// </summary>
        /// <param name="input">查询条件</param>
        /// <returns>库位设置列表</returns>
        public async Task<PagedResultDto<WarehouseLocationSettingDto>> GetListAsync(GetWarehouseLocationSettingListInput input)
        {
            var query = from location in _dbContext.Set<WarehouseLocationSettingModel>()
                        join area in _dbContext.Set<WarehouseAreaSettingModel>() on location.WarehouseAreaId equals area.Id into areaJoin
                        from area in areaJoin.DefaultIfEmpty()
                        join warehouse in _dbContext.Set<WarehouseSettingModel>() on area.WarehouseId equals warehouse.Id into warehouseJoin
                        from warehouse in warehouseJoin.DefaultIfEmpty()
                        select new WarehouseLocationSettingDto
                        {
                            Id = location.Id,
                            LocationCode = location.LocationCode,
                            LocationName = location.LocationName,
                            WarehouseAreaId = location.WarehouseAreaId,
                            WarehouseAreaName = area.AreaName,
                            WarehouseName = warehouse.DepotName,
                            Area = location.Area,
                            MaxCapacity = location.MaxCapacity,
                            LocationX = location.LocationX,
                            LocationY = location.LocationY,
                            LocationZ = location.LocationZ,
                            IsUsed = location.IsUsed,
                            Remark = location.Remark,
                            CreatedTime = location.CreatedTime,
                            UpdatedTime = location.UpdatedTime
                        };

            // 应用筛选条件
            if (!string.IsNullOrEmpty(input.LocationCode))
            {
                query = query.Where(x => x.LocationCode.Contains(input.LocationCode));
            }

            if (!string.IsNullOrEmpty(input.LocationName))
            {
                query = query.Where(x => x.LocationName.Contains(input.LocationName));
            }

            if (input.WarehouseAreaId.HasValue)
            {
                query = query.Where(x => x.WarehouseAreaId == input.WarehouseAreaId.Value);
            }

            if (input.IsUsed.HasValue)
            {
                query = query.Where(x => x.IsUsed == input.IsUsed.Value);
            }

            // 应用排序
            if (!string.IsNullOrEmpty(input.Sorting))
            {
                // 根据排序字段排序
                // 这里简化处理，实际可以根据需要添加更多排序字段
                if (input.Sorting.Contains("id", StringComparison.OrdinalIgnoreCase))
                {
                    query = input.Sorting.Contains("desc", StringComparison.OrdinalIgnoreCase)
                        ? query.OrderByDescending(x => x.Id)
                        : query.OrderBy(x => x.Id);
                }
                else if (input.Sorting.Contains("locationCode", StringComparison.OrdinalIgnoreCase))
                {
                    query = input.Sorting.Contains("desc", StringComparison.OrdinalIgnoreCase)
                        ? query.OrderByDescending(x => x.LocationCode)
                        : query.OrderBy(x => x.LocationCode);
                }
                else if (input.Sorting.Contains("locationName", StringComparison.OrdinalIgnoreCase))
                {
                    query = input.Sorting.Contains("desc", StringComparison.OrdinalIgnoreCase)
                        ? query.OrderByDescending(x => x.LocationName)
                        : query.OrderBy(x => x.LocationName);
                }
                else
                {
                    query = query.OrderByDescending(x => x.Id);
                }
            }
            else
            {
                query = query.OrderByDescending(x => x.Id);
            }

            // 获取总数
            var totalCount = await query.CountAsync();

            // 应用分页
            query = query.Skip((input.PageIndex - 1) * input.PageSize).Take(input.PageSize);

            // 获取数据
            var items = await query.ToListAsync();

            // 返回分页结果
            return new PagedResultDto<WarehouseLocationSettingDto>
            {
                Total = totalCount,
                Items = items
            };
        }

        /// <summary>
        /// 根据ID获取库位设置
        /// </summary>
        /// <param name="id">库位设置ID</param>
        /// <returns>库位设置</returns>
        public async Task<WarehouseLocationSettingDto> GetByIdAsync(int id)
        {
            var query = from location in _dbContext.Set<WarehouseLocationSettingModel>()
                        join area in _dbContext.Set<WarehouseAreaSettingModel>() on location.WarehouseAreaId equals area.Id into areaJoin
                        from area in areaJoin.DefaultIfEmpty()
                        join warehouse in _dbContext.Set<WarehouseSettingModel>() on area.WarehouseId equals warehouse.Id into warehouseJoin
                        from warehouse in warehouseJoin.DefaultIfEmpty()
                        where location.Id == id
                        select new WarehouseLocationSettingDto
                        {
                            Id = location.Id,
                            LocationCode = location.LocationCode,
                            LocationName = location.LocationName,
                            WarehouseAreaId = location.WarehouseAreaId,
                            WarehouseAreaName = area.AreaName,
                            WarehouseName = warehouse.DepotName,
                            Area = location.Area,
                            MaxCapacity = location.MaxCapacity,
                            LocationX = location.LocationX,
                            LocationY = location.LocationY,
                            LocationZ = location.LocationZ,
                            IsUsed = location.IsUsed,
                            Remark = location.Remark,
                            CreatedTime = location.CreatedTime,
                            UpdatedTime = location.UpdatedTime
                        };

            var result = await query.FirstOrDefaultAsync();
            // 返回结果，即使为null也不抛出异常
            return result;
        }

        /// <summary>
        /// 创建库位设置
        /// </summary>
        /// <param name="input">创建参数</param>
        /// <returns>创建后的库位设置</returns>
        public async Task<WarehouseLocationSettingDto> CreateAsync(CreateUpdateWarehouseLocationSettingDto input)
        {
            // 检查库区是否存在
            var area = await _warehouseAreaSettingRepository.FindAsync(input.WarehouseAreaId);
            if (area == null)
            {
                throw new Exception($"库区不存在: {input.WarehouseAreaId}");
            }

            // 检查编码是否已存在
            if (await IsCodeExistAsync(input.LocationCode))
            {
                throw new Exception($"库位编码已存在: {input.LocationCode}");
            }

            var entity = new WarehouseLocationSettingModel
            {
                LocationCode = input.LocationCode,
                LocationName = input.LocationName,
                WarehouseAreaId = input.WarehouseAreaId,
                Area = input.Area,
                MaxCapacity = input.MaxCapacity,
                LocationX = input.LocationX,
                LocationY = input.LocationY,
                LocationZ = input.LocationZ,
                IsUsed = input.IsUsed,
                Remark = input.Remark,
                CreatedTime = DateTime.Now
            };

            // 插入实体并获取ID
            var insertedEntity = await _warehouseLocationSettingRepository.InsertAsync(entity);
            await _dbContext.SaveChangesAsync();

            // 直接查询数据库获取完整数据，避免使用复杂的Join查询
            var warehouse = await _dbContext.Set<WarehouseSettingModel>()
                .Where(w => w.Id == area.WarehouseId)
                .FirstOrDefaultAsync();

            // 创建DTO并返回
            var result = new WarehouseLocationSettingDto
            {
                Id = insertedEntity.Id,
                LocationCode = insertedEntity.LocationCode,
                LocationName = insertedEntity.LocationName,
                WarehouseAreaId = insertedEntity.WarehouseAreaId,
                WarehouseAreaName = area.AreaName,
                WarehouseName = warehouse?.DepotName ?? string.Empty,
                Area = insertedEntity.Area,
                MaxCapacity = insertedEntity.MaxCapacity,
                LocationX = insertedEntity.LocationX,
                LocationY = insertedEntity.LocationY,
                LocationZ = insertedEntity.LocationZ,
                IsUsed = insertedEntity.IsUsed,
                Remark = insertedEntity.Remark,
                CreatedTime = insertedEntity.CreatedTime,
                UpdatedTime = insertedEntity.UpdatedTime
            };

            return result;
        }

        /// <summary>
        /// 更新库位设置
        /// </summary>
        /// <param name="id">库位设置ID</param>
        /// <param name="input">更新参数</param>
        /// <returns>更新后的库位设置</returns>
        public async Task<WarehouseLocationSettingDto> UpdateAsync(int id, CreateUpdateWarehouseLocationSettingDto input)
        {
            // 检查库位是否存在
            var entity = await _warehouseLocationSettingRepository.FindAsync(id);
            if (entity == null)
            {
                throw new Exception($"库位设置不存在: {id}");
            }

            // 检查库区是否存在
            var area = await _warehouseAreaSettingRepository.FindAsync(input.WarehouseAreaId);
            if (area == null)
            {
                throw new Exception($"库区不存在: {input.WarehouseAreaId}");
            }

            // 检查编码是否已存在（排除当前记录）
            if (await IsCodeExistAsync(input.LocationCode, id))
            {
                throw new Exception($"库位编码已存在: {input.LocationCode}");
            }

            // 更新实体
            entity.LocationCode = input.LocationCode;
            entity.LocationName = input.LocationName;
            entity.WarehouseAreaId = input.WarehouseAreaId;
            entity.Area = input.Area;
            entity.MaxCapacity = input.MaxCapacity;
            entity.LocationX = input.LocationX;
            entity.LocationY = input.LocationY;
            entity.LocationZ = input.LocationZ;
            entity.IsUsed = input.IsUsed;
            entity.Remark = input.Remark;
            entity.UpdatedTime = DateTime.Now;

            await _warehouseLocationSettingRepository.UpdateAsync(entity);
            await _dbContext.SaveChangesAsync();

            // 直接查询数据库获取完整数据，避免使用复杂的Join查询
            var warehouse = await _dbContext.Set<WarehouseSettingModel>()
                .Where(w => w.Id == area.WarehouseId)
                .FirstOrDefaultAsync();

            // 创建DTO并返回
            var result = new WarehouseLocationSettingDto
            {
                Id = entity.Id,
                LocationCode = entity.LocationCode,
                LocationName = entity.LocationName,
                WarehouseAreaId = entity.WarehouseAreaId,
                WarehouseAreaName = area.AreaName,
                WarehouseName = warehouse?.DepotName ?? string.Empty,
                Area = entity.Area,
                MaxCapacity = entity.MaxCapacity,
                LocationX = entity.LocationX,
                LocationY = entity.LocationY,
                LocationZ = entity.LocationZ,
                IsUsed = entity.IsUsed,
                Remark = entity.Remark,
                CreatedTime = entity.CreatedTime,
                UpdatedTime = entity.UpdatedTime
            };

            return result;
        }

        /// <summary>
        /// 删除库位设置
        /// </summary>
        /// <param name="id">库位设置ID</param>
        /// <returns>任务</returns>
        public async Task DeleteAsync(int id)
        {
            // 检查库位是否存在
            var entity = await _warehouseLocationSettingRepository.FindAsync(id);
            if (entity == null)
            {
                throw new Exception($"库位设置不存在: {id}");
            }

            // 删除实体
            await _warehouseLocationSettingRepository.DeleteAsync(id);
            await _dbContext.SaveChangesAsync();
        }

        /// <summary>
        /// 检查库位编码是否已存在
        /// </summary>
        /// <param name="code">库位编码</param>
        /// <param name="id">排除的ID</param>
        /// <returns>是否存在</returns>
        public async Task<bool> IsCodeExistAsync(string code, int id = 0)
        {
            return await _warehouseLocationSettingRepository.AnyAsync(x => x.LocationCode == code && x.Id != id);
        }
    }
} 